package org.xdj.blue.java.nio.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 服务端线程
 * @author 91power—xdj
 *
 */
public class NioSocketServer implements Runnable {
	public static Logger logger = LoggerFactory.getLogger(NioSocketServer.class);

	private Selector selector;
	private ServerSocketChannel serverSocketChannel;
	private volatile boolean stop;
	
	public NioSocketServer(int port){
		try {
			//创建多路复用器
			selector = Selector.open();
			//创建服务端通道
			serverSocketChannel = ServerSocketChannel.open();
			//设置非阻塞模式
			serverSocketChannel.configureBlocking(false);
			//监听9010端口
			serverSocketChannel.socket().bind(new InetSocketAddress(port),1024 );
			//注册到多路复用器
			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
			logger.debug("--服务端监听--"+port+"端口--");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void stop(){
		this.stop =true;
	}
	
	/**
	 * 执行
	 */
	public void run() {
		while(!stop){
			try {
				selector.select(10000);
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> it = keys.iterator();
				SelectionKey key = null;
				while(it.hasNext()){
					key = it.next();
					it.remove();
					try {
						handle(key);
					} catch (Exception e) {
						if(key !=null){
							key.channel().close();
						}
					}
				}
			} catch (Exception e) {
				
				e.printStackTrace();
			}
		}
	}

	/**
	 * 处理
	 * @param key
	 * @throws IOException
	 */
	private void handle(SelectionKey key) throws IOException{
		if(key.isValid()){
			if(key.isAcceptable()){
				logger.debug("--isAcceptable--");
				ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
				SocketChannel sc = ssc.accept();
				sc.configureBlocking(false);
				sc.register(selector, SelectionKey.OP_READ);
			}
			if(key.isReadable()){
				logger.debug("--isReadable--");
				SocketChannel sc = (SocketChannel) key.channel();
				ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
				int readBytes = sc.read(byteBuffer);
				if(readBytes>0){
					byteBuffer.flip();
					byte[] bytes = new byte[byteBuffer.remaining()];
					byteBuffer.get(bytes);
					String body = new String(bytes, "UTF-8");
					logger.debug("--服务端接受到信息："+body);
					String response = "I'm server! response you--" +new Date();
					doWrite(sc, response);
				}else if(readBytes <0){
					key.cancel();
					sc.close();
				}
			}
		}
	}
	
	/**
	 * 写入
	 * @param sc
	 * @param response
	 * @throws IOException
	 */
	private void doWrite(SocketChannel sc,String response) throws IOException{
		logger.debug("--doWrite--");
		
		if(response !=null && response.trim().length()>0){
			byte[] bytes = response.getBytes();
			ByteBuffer writeBuff = ByteBuffer.allocate(1024);
			writeBuff.put(bytes);
			writeBuff.flip();
			sc.write(writeBuff);
		}
	}
}
